from flask import Flask, request, jsonify
from lxml import etree
from index import *
import json, os, datetime, requests, html, re
app = Flask(__name__)


def template(page):
	return template_head + page + template_tail

def conf(filename):
	with open(filename, 'r') as hd:
		return json.loads(hd.read())

def rewrite(filename, new):
	if os.path.exists(filename):
		data = conf(filename)
	else:
		data = {}
	handle = open(filename, "w")
	data.update(new)
	handle.write(json.dumps(data))
	handle.close()

def renew(filename, new):
	if os.path.exists(filename):
		data = conf(filename)
	else:
		data = []
	handle = open(filename, "w")
	data.extend(new)
	handle.write(json.dumps(data))
	handle.close()

def note(message):
	with open('log.txt', 'a') as hd:
		hd.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')}: {message}\n")

def conf(filename):
	with open(filename, 'r') as hd:
		return json.loads(hd.read())

def resp(text):
	return '<p>' + text + '</p><script>setInterval("window.history.go(-1)", 3000);</script>'

def sche_add(cmd, tm):
	return


def tbs(tok):
	sign = json.loads(requests.get('http://tieba.baidu.com/dc/common/tbs', cookies = {
		'BDUSS': tok
	}).text)
	if sign['is_login'] != 1:
		return False, sign
	else:
		return True, sign['tbs']

def fid(tb):
	bar = json.loads(requests.get('http://tieba.baidu.com/f/commit/share/fnameShareApi', params = {
		'ie': 'utf-8',
		'fname': tb
	}).text)
	if bar['no'] != 0 or bar['data']['fid'] == 0: return -1, bar
	else: return bar['data']['fid'], tb

def ban(un, tb, day):
	info = json.loads(requests.get('https://tieba.baidu.com/home/get/panel', params = {
		'ie': 'utf-8',
		'un': un
	}).text)
	if info['no'] != 0: return {'stat': False, 'msg': f"failed to get user info {info}"}
	bar = fid(tb)
	if bar[0] < 1:
		return {'stat': False, 'msg': f"failed to get bar info {bar[1]}"}
	bar = bar[0]
	sign = tbs(conf('conf.json')['tok'])
	if not sign[0]: return {'stat': False, 'msg': f"failed to get tb sign {sign[1]}"}
	sign = sign[1]
	res = json.loads(requests.post('https://tieba.baidu.com/pmc/blockid', data = {
		'day': day,
		'fid': bar,
		'tbs': sign,
		'user_name[]': info['data']['name'].encode('gbk'),
		'portrait[]': info['data']['portrait'].split('?')[0],
		'reason': '\0',
	}, cookies = {
		'BDUSS': conf('conf.json')['tok']
	}).text)
	if res['errno'] == 0: return {'stat': True}
	else: return {'stat': False, 'msg': f"{res}"}

def delete(link, mask):
	html = etree.HTML(requests.get(link).text, etree.HTMLParser())
	name = html.xpath('/html/head/meta[4]/@fname')
	if len(name) < 1:
		return {'stat': False, 'msg': f"failed to get post info, maybe it is already deleted"}
	name = name[0]
	bar = fid(name)
	if bar[0] < 1:
		return {'stat': False, 'msg': f"failed to get bar info {bar[1]}"}
	bar = bar[0]
	sign = tbs(conf('conf.json')['tok'])
	if not sign[0]: return {'stat': False, 'msg': f"failed to get tb sign {sign[1]}"}
	sign = sign[1]
	tid = link.split('/')[-1]
	res = json.loads(requests.post('https://tieba.baidu.com/f/commit/thread/delete', data = {
		'tbs': sign,
		'fid': bar,
		'tid': tid,
		'is_frs_mask': mask,
		'reason': '0'
	}, cookies = {
		'BDUSS': conf('conf.json')['tok']
	}).text)
	if res['no'] == 0: return {'stat': True}
	else: return {'stat': False, 'msg': f"{res}"}
	return


@app.route('/')
def index():
	return template(index_page)

@app.route('/log')
def log():
	if os.path.exists('log.txt'):
		with open('log.txt', 'r') as hd:
			content = hd.read()
		return html.escape(content).replace('\n', '<br>')
	else:
		return "log is empty"


@app.route('/u')
def user():
	return template(user_page)

@app.route('/u/ban')
def user_ban():
	return template(u_ban)

@app.route('/u/loop')
def user_loop():
	return template(u_loop)


@app.route('/p')
def post():
	return template(post_page)

@app.route('/p/del')
def post_del():
	return template(p_del)


@app.route('/api/tk', methods = ['POST'])
def api_token():
	data = json.loads(request.get_data(as_text = True))
	rewrite("conf.json", {'tok': data['tok']})
	note(f"Set BDUSS to {data['tok']}")
	return jsonify({'tok': data['tok']})

@app.route('/api/id')
def api_identify():
	if os.path.exists('conf.json'):
		if 'tok' in conf('conf.json'):
			return jsonify({ 'set': True, 'rs': 'success' })
		else:
			return jsonify({ 'set': False, 'rs': 'key does not exist' })
	else:
		return jsonify({ 'set': False, 'rs': 'file does not exist' })


@app.route('/api/u_ban', methods = ['POST'])
def api_u_ban():
	data = request.form
	res = ban(data['un'], data['tb'], data['tp'])
	if res['stat']:
		note(f"Ban {data['un']} in {data['tb']} bar for {data['tp']} days")
		return resp("封禁成功，3秒后返回上一页")
	else:
		note(f"Failed to ban {data['un']} in {data['tb']} bar, error message: {res['msg']}")
		return resp("封禁失败，已经记录在日志中，3秒后返回上一页")

@app.route('/api/u_loop', methods = ['POST'])
def api_u_loop():
	data = request.form
	day = 0
	if data['tp'] == "0": day = 10
	elif data['tp'] == "1": day = 1
	elif data['tp'] == "2": day = 3
	sche_add(f"ban({data['un']}, {data['tb']}, {day})", day * 86400)
	note(f"Loop ban {data['un']} in {data['tb']} bar, type id {data['tp']}")
	return resp("已经添加循环封禁，3秒后返回上一页")


@app.route('/api/p_del', methods = ['POST'])
def api_p_del():
	data = request.form
	if not re.match("(?:https\:\/\/|http\:\/\/|)tieba.baidu.com\/p\/", data['link']):
		note(f"Failed to delete post {data['link']}, format error")
		return resp("链接格式错误，3秒后返回上一页")
	link = data['link'].split('?')[0]
	res = delete(link, data['mask'])
	if res['stat']:
		note(f"Delete post {data['link']}, operation {data['mask']}")
		return resp("删除成功，3秒后返回上一页")
	else:
		note(f"Failed to delete post {data['link']}, error message: {res['msg']}")
		return resp("删除失败，已经记录在日志中，3秒后返回上一页")


app.run(host = '0.0.0.0', port = 9961) # use 0.0.0.0 instead of 127.0.0.1 for LAN visit
